package com.gitee.wsl.serialization.id

import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.jvm.JvmName
import kotlin.jvm.JvmStatic

/**
 * 一个通过 [64位整型 (Long)][Long] 作为ID值的 [NumericalID] 实现。
 *
 *  @property value 源值。
 */
@Serializable(with = LongID.Serializer::class)
public class LongID private constructor(public val value: Long) : SignedNumericID() {
    override fun toDouble(): Double = value.toDouble()
    override fun toFloat(): Float = value.toFloat()
    override fun toLong(): Long = value
    override fun toInt(): Int = value.toInt()
    override fun toShort(): Short = value.toShort()
    override fun toByte(): Byte = value.toByte()
    override fun toString(): String = value.toString()
    override fun hashCode(): Int = value.hashCode()

    override fun equals(other: Any?): Boolean = idCommonEq(other) {
        when (it) {
            is NumericalID -> compareNumber(it) == 0
            else -> value.toString() == it.toString()
        }
    }

    override fun equalsExact(other: Any?): Boolean = idExactEq(other) {
        value == it.value
    }

    override fun compareNumber(target: NumericalID): Int = compareLongID(target)

    override fun copy(): LongID = LongID(value)

    public companion object {
        /**
         * 将一个 [Long] 转化为 [LongID]。
         */
        @get:JvmStatic
        @get:JvmName("valueOf")
        public val Long.ID: LongID
            get() = LongID(this)

    }

    /**
     * [LongID] 的序列化器。不出意外地将 [LongID] 作为 [Long] 进行序列化。
     */
    public object Serializer : KSerializer<LongID> {
        override val descriptor: SerialDescriptor =
            PrimitiveSerialDescriptor("LongID", PrimitiveKind.LONG)
        override fun deserialize(decoder: Decoder): LongID = decoder.decodeLong().ID
        override fun serialize(encoder: Encoder, value: LongID) {
            encoder.encodeLong(value.value)
        }
    }
}